package com.excilys.formation.project.controllers;

import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.joda.time.YearMonth;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.excilys.formation.project.controllers.util.AuthentifiedClientManager;
import com.excilys.formation.project.entities.Client;
import com.excilys.formation.project.entities.Compte;
import com.excilys.formation.project.entities.Operation;
import com.excilys.formation.project.entities.TypeOperation;
import com.excilys.formation.project.services.CompteService;
import com.excilys.formation.project.services.OperationService;

/**
 * Controleur de l'affichage des données des comptes.
 * 
 * @author excilys
 * 
 */
@Controller
@RequestMapping(value = "/secure/compte")
public class CompteController {

    /**
     * Service gérant les opérations.
     */
    @Autowired
    private OperationService operationService;
    /**
     * Service gérant les comptes.
     */
    @Autowired
    private CompteService compteService;
    /**
     * Gère la récupération du client en session.
     */
    @Autowired
    private AuthentifiedClientManager authentifiedClientManager;

    @RequestMapping(method = RequestMethod.GET)
    public String getView(final Model model) {
        Client connectedClient = authentifiedClientManager.getSessionClient();
        Set<Compte> sortedComptes = new TreeSet<Compte>(connectedClient.getComptes());

        Map<String, Double> SumEncoursClient = operationService.getSumEncoursByClient(connectedClient.getId());

        System.err.println(SumEncoursClient);
        model.addAttribute("encours", SumEncoursClient);

        model.addAttribute("comptes", sortedComptes);
        model.addAttribute(connectedClient);

        return "secure/compte/index";
    }

    @RequestMapping(method = RequestMethod.GET, value = "/{numero}/{mois}/export")
    protected String getExcel(@PathVariable String numero, @PathVariable String mois, HttpServletRequest request, HttpServletResponse response,
            Model model) {

        YearMonth month = YearMonth.parse(mois);
        List<Operation> compteData = operationService.getOperationsByCompteByYearMonth(numero, month);
        Client connectedClient = authentifiedClientManager.getSessionClient();

        model.addAttribute("client", connectedClient);
        model.addAttribute("compteData", compteData);
        return "excelView";
    }

    /**
     * 
     * @param numero
     *            numéro du compte à afficher
     * @param model
     *            instance de ModelMap
     * @return le chemin vers la jsp
     */
    @RequestMapping(method = RequestMethod.GET, value = "/{numero}")
    public String showOperations(@PathVariable String numero, Model model) {
        return "redirect:" + numero + "/" + YearMonth.now();
    }

    /**
     * 
     * @param numero
     *            numéro du compte à afficher
     * @param model
     *            instance de ModelMap
     * @param mois
     *            mois à vérifier
     * @return le chemin vers la jsp
     */
    @RequestMapping(method = RequestMethod.GET, value = "/{numero}/{mois}")
    public String showOperations(@PathVariable String numero, @PathVariable String mois, Model model) {
        Client connectedClient = authentifiedClientManager.getSessionClient();
        Compte compte = compteService.getCompte(numero);
        if (compte.getClient().getId() != connectedClient.getId()) {
            throw new ResourceNotFoundException();
        }
        YearMonth month = YearMonth.parse(mois);
        List<Operation> operations = operationService.getOperationsByCompteByYearMonthExceptType(numero, month, TypeOperation.CARTE);
        double sommeCarte = operationService.getSumOperationsByCompteByYearMonthAndType(numero, month, TypeOperation.CARTE);

        DateTimeFormatter dateFormatter = DateTimeFormat.forStyle("LS");
        dateFormatter = dateFormatter.withLocale(Locale.FRANCE);

        model.addAttribute("dateFormatter", dateFormatter);

        model.addAttribute("previousMonth", month.minusMonths(1));
        model.addAttribute("currentMonth", month);
        model.addAttribute("hasNextMonth", month.isBefore(YearMonth.now()));
        model.addAttribute("nextMonth", month.plusMonths(1));

        model.addAttribute(compte);
        model.addAttribute("operations", operations);
        model.addAttribute("sommeCarte", sommeCarte);
        return "secure/compte";
    }

    @RequestMapping(method = RequestMethod.GET, value = "/carte/{numero}/{mois}")
    public String showCardOperations(@PathVariable String numero, @PathVariable String mois, Model model) {
        Client connectedClient = authentifiedClientManager.getSessionClient();
        Compte compte = compteService.getCompte(numero);
        if (compte.getClient().getId() != connectedClient.getId()) {
            throw new ResourceNotFoundException();
        }
        YearMonth month = YearMonth.parse(mois);
        List<Operation> operations = operationService.getOperationsByCompteByYearMonthAndType(numero, month, TypeOperation.CARTE);

        DateTimeFormatter dateFormatter = DateTimeFormat.forStyle("LS");
        dateFormatter = dateFormatter.withLocale(Locale.FRANCE);

        model.addAttribute("dateFormatter", dateFormatter);

        model.addAttribute("previousMonth", month.minusMonths(1));
        model.addAttribute("currentMonth", month);
        model.addAttribute("hasNextMonth", month.isBefore(YearMonth.now()));
        model.addAttribute("nextMonth", month.plusMonths(1));

        model.addAttribute(compte);
        model.addAttribute("operations", operations);
        return "secure/compte";
    }
}
